<template>
  <grid-form
    v-if="pageForm && pageForm.grid && !meta?.some((x) => x.type == 'blob')"
    ref="form"
    v-model="form"
    :fields="meta"
    :page="pageForm"
    module="form"
  />
  <el-form v-else ref="form" v-bind="formConfig" :model="form" :rules="rules">
    <template v-for="col in meta" :key="col.key">
      <el-form-item
        :class="{ 'batch-upload': col.batch_upload }"
        :label="col.name"
        v-if="col.editable && checkVisible(col)"
        :required="col.require"
        :prop="col.key"
      >
        <el-input v-if="col.type === 'string'" v-model="form[col.key]" />
        <el-input
          v-else-if="col.type === 'textarea' || col.type === 'text'"
          type="textarea"
          :rows="col.rows || 10"
          v-model="form[col.key]"
        />
        <el-input v-else-if="col.type === 'number'" type="number" v-model="form[col.key]" />
        <el-input v-else-if="col.type === 'int'" type="number" v-model="form[col.key]" />
        <el-input v-else-if="col.type === 'float'" type="number" v-model="form[col.key]" />
        <el-input
          v-else-if="col.type === 'password'"
          type="password"
          show-password
          v-model="form[col.key]"
        />
        <el-select
          v-else-if="col.type === 'enum'"
          filterable
          clearable
          allow-create
          v-model="form[col.key]"
          placeholder="请选择"
        >
          <template v-for="(val, index) in col.values" :key="index">
            <el-option v-if="typeof val === 'object'" :label="val.name" :value="val.key" />
            <el-option v-else :label="val" :value="val" />
          </template>
        </el-select>
        <el-select
          v-else-if="col.type === 'list'"
          filterable
          clearable
          allow-create
          multiple
          collapse-tags
          v-model="form[col.key]"
          placeholder="请选择"
        >
          <template v-for="(val, index) in col.values" :key="index">
            <el-option v-if="typeof val === 'object'" :label="val.name" :value="val.key" />
            <el-option v-else :label="val" :value="val" />
          </template>
        </el-select>
        <el-slider
          v-else-if="col.type === 'range'"
          v-model="form[col.key]"
          :min="col.range[0]"
          :max="col.range[1]"
        />
        <el-date-picker
          v-else-if="col.type === 'datetime'"
          v-model="form[col.key]"
          type="datetime"
          placeholder="选择日期时间"
        />
        <el-checkbox v-else-if="col.type === 'bool'" v-model="form[col.key]" />
        <el-color-picker
          v-else-if="col.type === 'color'"
          v-bind="col.props"
          v-model="form[col.key]"
          show-alpha
        />
        <el-upload
          v-else-if="col.type === 'blob'"
          class="upload-attachment"
          action=""
          name="upload_file"
          :before-upload="(file) => beforeUpload(file, col)"
        >
          <el-tag closable v-if="form[col.key]" @close="form[col.key] = undefined">
            {{ form[col.key]?.name }}
          </el-tag>
          <el-button v-else size="small" type="primary">点击上传</el-button>
          <template #tip>
            <div v-if="col.hint" class="el-upload__tip">
              {{ col.hint }}
            </div>
          </template>
        </el-upload>
        <template v-else-if="col.type === 'file'">
          <template v-if="col.batch_upload && form && col && !form.id">
            <el-button @click="addUploadList">
              <Icon icon="material-symbols:add" />新增上传
            </el-button>
            <div class="batch-upload" v-for="(up, i) in batchUploadList" :key="i">
              <meta-upload
                v-model="up.data"
                :meta="col"
                @change="(file) => uploadChange(file, col)"
              />

              <div class="close" @click.stop="removeUploadList(i)"
                ><Icon :size="16" icon="material-symbols:close"
              /></div>
            </div>
          </template>
          <template v-else>
            <meta-upload
              v-if="form && col"
              v-model="form[col.key]"
              :meta="col"
              @change="(file) => uploadChange(file, col)"
            />
          </template>
        </template>
        <el-upload
          v-else-if="col.type === 'fileset'"
          class="upload-attachment multiple"
          action="/api/dataio/input_uploader/upload"
          name="upload_file"
          :data="{ save_dir: 'None', event: 'None' }"
          :headers="{ token }"
          multiple
          :limit="10"
          :on-exceed="handleExceed"
          :on-success="(file) => handleSuccess(file, col)"
          :on-remove="(file) => handleRemove(file, col)"
        >
          <el-button size="small" type="primary">点击上传</el-button>
          <template #tip>
            <div v-if="col.hint" class="el-upload__tip">
              {{ col.hint }}
            </div>
          </template>
        </el-upload>
      </el-form-item>
    </template>
  </el-form>
</template>

<script>
import MetaUpload from './Upload.vue'
import { getFormValues } from '@/api/basic'
import { useCache } from '@/hooks/web/useCache'
import { ElMessage } from 'element-plus'
import { initRemoteValues, getDefaultGridPage } from '../utils/table'
import GridForm from '../AutoGrid/index.vue'

const { wsCache } = useCache()
export default {
  name: 'MetaForm',
  components: { MetaUpload, GridForm },
  props: {
    modelValue: {
      type: Object,
      default: () => ({})
    },
    meta: {
      type: Array,
      default: () => []
    },
    config: {
      type: Object,
      default: () => ({})
    }
  },
  data() {
    return {
      rules: {},
      token: wsCache.get('Admin-Token'),
      batchUploadList: [{ data: {} }],
      pageForm: {}
    }
  },
  computed: {
    form: {
      get: function () {
        return this.modelValue
      },
      set: function (value) {
        this.$emit('update:modelValue', value)
      }
    },
    formConfig() {
      return {
        'label-width': '120px',
        ...this.config
      }
    }
  },
  watch: {
    meta: {
      handler() {
        this.rules = this.meta.reduce((t, c) => {
          if (c.editable && c.require) {
            t[c.key] = [
              {
                required: true,
                message: (c.type === 'enum' ? '请选择' : '请输入') + c.name,
                trigger: ['enum', 'list', 'range'].includes(c.type) ? ['change', 'blur'] : 'blur'
              }
            ]
          }
          return t
        }, {})
        this.$refs.form?.resetFields()
      },
      // deep: true,
      immediate: true
    }
  },
  created() {
    this.initPageForm()
  },
  mounted() {
    // initRemoteValues(this.meta)
  },
  methods: {
    initPageForm() {
      this.pageForm = getDefaultGridPage(this.meta, 'form')
    },
    validate(callback) {
      this.$refs.form.validate(async (valid) => {
        if (valid) {
          Object.keys(this.form).forEach((k) => {
            const field = this.meta.find((m) => m.key === k)
            if (
              field &&
              field.require &&
              field.type === 'file' &&
              typeof this.form[k] === 'object' &&
              !this.form[k]?.upload_url
            ) {
              ElMessage({
                type: 'warning',
                message: `[${field.name}]请上传文件`
              })
              valid = false
            }
          })
        }
        if (typeof callback === 'function') {
          callback(valid)
        }
      })
    },
    resetFields() {
      this.$nextTick(() => {
        this.$refs.form.resetFields()
      })
    },
    validateField(field) {
      this.$nextTick(() => {
        this.$refs.form.validateField(field)
      })
    },
    handleExceedSingle(files, fileList) {
      this.$message.warning(`当前为单选，请先删除已上传的文件`)
    },
    handleSuccessSingle(res, col) {
      this.form[col.key] = res.file
      this.validateField(col.key)
    },
    handleRemoveSingle(file, col) {
      this.form[col.key] = ''
      this.validateField(col.key)
    },
    handleExceed(files, fileList) {
      this.$message.warning(
        `当前限制选择 1 个文件，本次选择了 ${files.length} 个文件，共选择了 ${
          files.length + fileList.length
        } 个文件`
      )
    },
    handleSuccess(res, col) {
      this.form[col.key] = this.form[col.key] ? this.form[col.key] + ',' + res.file : res.file
      console.log(this.form[col.key])
      this.validateField(col.key)
    },
    handleRemove(res, col) {
      const val = this.form[col.key]
      if (val.split(',').length > 1) {
        this.form[col.key] = val.replace(',' + res.response.file, '')
      } else {
        this.form[col.key] = val.replace(res.response.file, '')
      }
      this.validateField(col.key)
    },
    beforeUpload(res, col) {
      this.form[col.key] = res
      return false
    },
    getFileList(col) {
      const url = this.form[col.key] || ''
      if (url) {
        const names = url.split('/')
        return [{ name: names[names.length - 1], url }]
      }
      return []
    },
    addUploadList() {
      this.batchUploadList.push({ data: {} })
    },
    removeUploadList(index) {
      this.batchUploadList.splice(index, 1)
    },
    getBatchList() {
      return this.batchUploadList
    },
    uploadChange(file, col) {
      this.validateField(col.key)
    },
    checkVisible(col) {
      if (col.visible) {
        return col?.visible?.exclude
          ? ![col?.visible?.value].flat().includes(this.form?.[col?.visible?.field])
          : [col?.visible?.value].flat().includes(this.form?.[col?.visible?.field])
      }
      return true
    },
    getData() {
      return this.modelValue
    }
  }
}
</script>

<style scoped lang="less">
:deep(.upload-attachment) {
  .el-upload-list {
    flex: 0 0 300px;
  }

  &.multiple {
    width: 300px;
  }

  &.single {
    display: flex;
    align-items: center;
  }
}
:deep(.el-form-item) {
  &.batch-upload {
    .el-form-item__content {
      align-items: flex-start;
      flex-direction: column;
    }

    .batch-upload {
      position: relative;
      display: flex;
      width: 100%;
      align-items: flex-end;

      .close {
        font-size: 16px;
        cursor: pointer;
        background: #ccc;
        color: #fff;
        display: inline-block;
        width: 16px;
        height: 16px;
        line-height: 16px;
        text-align: center;
        border-radius: 100%;
        margin: 10px;

        &:hover {
          background-color: #aaa;
        }
      }
    }
  }
}
</style>
